﻿using System;
using System.Linq;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;
using Uportal.Shp.Core.Common;
using Uportal.Shp.Core.Const;
using Uportal.Shp.Core.Enums;
using SharepointCommon;
using Uportal.Shp.Core.Services;
using System.Collections.Generic;
using Uportal.Shp.Core.Model;

namespace Uportal.Shp.Core.ER
{
    public class ERFeedBack : SPItemEventReceiver
    {
        NLogLogger _logger = new NLogLogger(@"c:\Temp\Logs\Uportal.ER_${shortdate}.log");
        
        
        public override void ItemAdded(SPItemEventProperties properties)
        {
            try
            {
                _logger.Info("ERFeedback event handler added starts");
                EventFiringEnabled = false;

                base.ItemAdded(properties);
                
                var item = properties.ListItem;
                
                itemForApproved(item);

                //получаем пользователей в группе "Модератор"и отправляем им письмо
                using (var w = WebFactory.Open(properties.Web.Url))
                {
                    _logger.Info("properties.Web.Url:" + properties.Web.Url);

                    SPGroup group = w.Web.Groups[GetGroupName(w.Web.Url)]; 
                    string message = String.Format("На портале заведен новый <a href='{0}'>вопрос</a>.<br/> Пожалуйста,утвердите или закройте его.",
                       w.Web.Url + item.ParentList.Forms[PAGETYPE.PAGE_EDITFORM].ServerRelativeUrl + "?ID=" + item.ID.ToString());
        
                    foreach (SPUser user in group.Users)
                    {
                       MailHelper.SendEmail(w.Web, user.Email, FeedbackManager.SubjForModerator, message);
                    }
                }
            }
            catch (Exception ex)
            {
                SPSecurity.RunWithElevatedPrivileges(() => _logger.Exception(ex));
            }
            finally
            {
                EventFiringEnabled = true;
                _logger.Info("ERFeedback event handler added finish");
            }
        }

        public override void ItemUpdated(SPItemEventProperties properties)
        {
            try
            {
                _logger.Info("ERFeedback event handler updated starts");
                this.EventFiringEnabled = false;
                base.ItemUpdated(properties);
                
                var item = properties.ListItem;
                string state = Convert.ToString(item[FieldInfo.Feedback.StateQuestion]);


                if (state == EnumResolver.GetStringValue(StateQuestion.Approved))
                {
                    if (item[FieldInfo.Feedback.IsApproved] == null)
                        itemToManger(item);
                    else
                        itemIsAnswer(item);
                        
                }

                //if (state == EnumResolver.GetStringValue(StateQuestion.ForApproved))
                //{
                //    itemToManger(item);
                //}
                
                if (state == EnumResolver.GetStringValue(StateQuestion.Closed))
                {
                    itemClosed(item);
                }

                _logger.Info("ERFeedback event handler updated finished");
            }

            catch (Exception ex)
            {
                SPSecurity.RunWithElevatedPrivileges(() => _logger.Exception(ex));
            }
            finally
            {
                this.EventFiringEnabled = true;
            }
        }

        private void itemForApproved(SPListItem item)
        {
            try
            {
                string title = (Convert.ToString(item[FieldInfo.Feedback.Question])).Replace("<div>", string.Empty).Replace("</div>", string.Empty);
                item["Title"] = title.Length > 30 ? title.Substring(0, 20) + "..." : title;
                item[FieldInfo.Feedback.StateQuestion] = EnumResolver.GetStringValue(StateQuestion.ForApproved);
                item.Update();
               
                // разрешения только для модератора и создателя
                SPSecurity.RunWithElevatedPrivileges(() =>
                {
                    using (var site = new SPSite(item.Web.Url))
                    {
                        using (var web = site.OpenWeb())
                        {
                            var list = web.Lists.TryGetList(item.ParentList.Title);
                            var reloadedItem = list.GetItemByUniqueId(item.UniqueId);
                            //анонимность вопроса
                            TypeQuestion tq = EnumResolver.GetEnumValue<TypeQuestion>(Convert.ToString(reloadedItem[FieldInfo.Feedback.TypeQuestion]));
                            if (tq == TypeQuestion.Anonim)
                            {
                                reloadedItem[SPBuiltInFieldId.Author] = reloadedItem.Web.SiteAdministrators[0];
                                reloadedItem.Update();
                            }
                        
                            clearPerrmisions(reloadedItem);
                            if(tq != TypeQuestion.Anonim)
                               setRoleForAuthor(reloadedItem, SPRoleType.Reader);
                            setRoleForModerator(reloadedItem, SPRoleType.Contributor);
                        }
                    }
                });


            }
            catch (Exception ex)
            {
                SPSecurity.RunWithElevatedPrivileges(() => _logger.Exception(ex));
            }
        }

        private void itemIsAnswer(SPListItem item)
        {
            item[FieldInfo.Feedback.StateQuestion] = EnumResolver.GetStringValue(StateQuestion.Answered);
            item[FieldInfo.Feedback.DateOfAnswer] = DateTime.Now;
            item.Update();

            SPSecurity.RunWithElevatedPrivileges(() =>
            {
                using (var site = new SPSite(item.Web.Url))
                {
                    using (var web = site.OpenWeb())
                    {
                        var list = web.Lists.TryGetList(item.ParentList.Title);
                        var reloadedItem = list.GetItemByUniqueId(item.UniqueId);

                        clearPerrmisions(reloadedItem);
                        TypeQuestion tq = EnumResolver.GetEnumValue<TypeQuestion>(Convert.ToString(reloadedItem[FieldInfo.Feedback.TypeQuestion]));
                        if (tq == TypeQuestion.Anonim) setPublicRole(reloadedItem);
                        else
                        {
                            if (tq == TypeQuestion.Public) setPublicRole(reloadedItem);
                            else
                            {
                                setRoleForAuthor(reloadedItem, SPRoleType.Reader);
                                setRoleForModerator(reloadedItem, SPRoleType.Contributor);
                                setRoleForManager(reloadedItem, SPRoleType.Reader);
                            }
                        }
                    }
                }
            });
        }

        private void itemToManger(SPListItem item)
        {
            item[FieldInfo.Feedback.StateQuestion] = EnumResolver.GetStringValue(StateQuestion.Approved);
            item[FieldInfo.Feedback.IsApproved] = true; 
            item.Update();
            SPSecurity.RunWithElevatedPrivileges(() =>
            {
                using (var site = new SPSite(item.Web.Url))
                {
                    using (var web = site.OpenWeb())
                    {
                        var list = web.Lists.TryGetList(item.ParentList.Title);
                        var reloadedItem = list.GetItemByUniqueId(item.UniqueId);

                        clearPerrmisions(reloadedItem);

                        setRoleForAuthor(reloadedItem, SPRoleType.Reader);
                        setRoleForModerator(reloadedItem, SPRoleType.Reader);
                        setRoleForManager(reloadedItem, SPRoleType.Contributor);
                    }
                }
            });

            // отправляем письмо руководителю
            using (var w = WebFactory.Open(item.Web.Url))
            {
                var user = UserHelper.GetSiteUserByRawName(w.Web, Convert.ToString(item[FieldInfo.Feedback.Whom]));
                SPGroup group = w.Web.Groups[GetGroupName(w.Web.Url)];
                
                string message = String.Format("На портале для Вас опубликован новый <a href='{0}'>вопрос</a>.<br/> Пожалуйста, ответьте на него.",
                    w.Web.Url + item.ParentList.Forms[PAGETYPE.PAGE_EDITFORM].ServerRelativeUrl + "?ID=" + item.ID.ToString());

                _logger.Info("user.Email:" + user.Email);
                _logger.Info("FeedbackManager.SubjForNamager:" + FeedbackManager.SubjForNamager);
                _logger.Info("message:" + message);


                MailHelper.SendEmail(w.Web, user.Email, FeedbackManager.SubjForNamager, message);
            }
        }

        private void itemClosed(SPListItem item)
        {
            item[FieldInfo.Feedback.IsApproved] = false;
            item.Update();
            SPSecurity.RunWithElevatedPrivileges(() =>
            {
                using (var site = new SPSite(item.Web.Url))
                {
                    using (var web = site.OpenWeb())
                    {
                        var list = web.Lists.TryGetList(item.ParentList.Title);
                        var reloadedItem = list.GetItemByUniqueId(item.UniqueId);

                        clearPerrmisions(reloadedItem);
                        if (Convert.ToString(reloadedItem[FieldInfo.Feedback.TypeQuestion]) == EnumResolver.GetStringValue(TypeQuestion.Public))
                            setPublicRole(reloadedItem);
                        else
                        {
                            setRoleForAuthor(reloadedItem, SPRoleType.Reader);
                            setRoleForModerator(reloadedItem, SPRoleType.Contributor);
                            setRoleForManager(reloadedItem, SPRoleType.Reader);
                        }
                    }
                }
            });
            // отправляем письмо инициатору о закрытии вопроса
            using (var w = WebFactory.Open(item.Web.Url))
            {
                var user = UserHelper.GetSiteUserByRawName(w.Web, Convert.ToString(item[SPBuiltInFieldId.Author]));
                MailHelper.SendEmail(w.Web, user.Email, "Test subject for author", "Test body for author");
            }
        }

        private void setPublicRole(SPListItem item)
        {
            var assignments = item.ParentList.RoleAssignments;
            var pm = new PermitManager(item);

            foreach (SPRoleAssignment ra in assignments)
            {
                pm.AddPermission(ra.Member, SPRoleType.Reader, true);
            }
            setRoleForModerator(item, SPRoleType.Contributor);
        }

        private void setRoleForAuthor(SPListItem item, SPRoleType typeRole)
        {
            var pm = new PermitManager(item);
            var field = (SPFieldUser)item.Fields[SPBuiltInFieldId.Author];
            var user = (SPFieldUserValue)field.GetFieldValue(item[SPBuiltInFieldId.Author].ToString());
            pm.AddPermission(user.User as SPPrincipal, typeRole, true);
        }

        private void setRoleForModerator(SPListItem item, SPRoleType typeRole)
        {
            var pm = new PermitManager(item);
            var user = item.ParentList.ParentWeb.Groups[GetGroupName(item.Web.Url)];// as SPPrincipal;
            //foreach (SPUser user in item.ParentList.ParentWeb.Groups[Settings.Get().ModeratorGroup].Users)
           // {
                pm.AddPermission(user as SPPrincipal, typeRole, true);
            //}
        }

        private void setRoleForManager(SPListItem item, SPRoleType typeRole)
        {
            var pm = new PermitManager(item);
            var fieldGuid = item.Fields.GetField(FieldInfo.Feedback.Whom).Id;
            var fieldManager = (SPFieldUser)item.Fields[fieldGuid];
            var manager = (SPFieldUserValue)fieldManager.GetFieldValue(item[FieldInfo.Feedback.Whom].ToString());
            pm.AddPermission(manager.User as SPPrincipal, typeRole, true);
        }

        private void clearPerrmisions(SPListItem item)
        {
            var pm = new PermitManager(item);
            pm.ClearPermissions();
        }

        private string GetGroupName(string webUrl)
        {
            string url = string.Empty;
            using (var w = WebFactory.Open(webUrl))
            {
                _logger.Info("webUrl:" + webUrl);
                _logger.Info("UportalSettingListUrl:" + ListInfo.UportalSettingListUrl);
                var item =  w.GetByUrl<UportalSettings>(ListInfo.UportalSettingListUrl).Items(CamlQuery.Default).FirstOrDefault();
                _logger.Info("item.ModeratorGroup:" + item.ModeratorGroup);
                return item.ModeratorGroup;
            }
            return url;
        }

    }
}